package com.solidtrust.crawler.service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.zip.GZIPInputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.solidtrust.admin.service.ImageExtractor;
import com.solidtrust.app.FileSystemUtil;
import com.solidtrust.dao.CommonDao;
import com.solidtrust.entity.CarImage;
import com.solidtrust.util.HttpUtil;

@Service
public class ImageService {
	private static final Logger log4j = Logger.getLogger(ImageService.class);
	private static final String START_URL = "http://api.car.bitauto.com/CarInfo/getlefttreejson.ashx?tagtype=tupian&pagetype=masterbrand&objid={0}";
	private static final String PREFIX = "http://photo.bitauto.com/serialmore/";
	private static final String PREFIX1 = "http://photo.bitauto.com/serial/";
	private static final String PREFIX2 = "http://photo.bitauto.com/picture/"; 
	private static final String IMAGE_LIST = "http://photo.bitauto.com/API/GetSourceImageListForSerialBrand.ashx?serialBrandID={1}&sourceID={0}&pageNum=1&pageSize=20";
	
	private static final int TIMEOUT = 1000 * 10;
	private ObjectMapper om = new ObjectMapper();
	private List<_Brand> _brands = new ArrayList<>();
	
	@Autowired CommonDao dao;
	@Autowired ImageExtractor extractor;
	
	public void start() throws IOException{
		om.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		json(new _Brand("A", 9, 0, "奥迪"));
	}
	
	public void json(_Brand _b) throws IOException{
		String s = MessageFormat.format(START_URL, _b.id);
		String result = sendRequest(s, true);
		if(result != null){
			result = result.substring("JsonpCallBack(".length(), result.length() - 1);
			JsonNode brandNode = om.readTree(result).get("brand");
			if(_brands.isEmpty()){
				Iterator<String> it = brandNode.fieldNames();
				while(it.hasNext()){
					String ch = it.next();
					ArrayNode an = (ArrayNode) brandNode.get(ch);
					for (int i = 0; i < an.size(); i++) {
						JsonNode item = an.get(i);
						_brands.add(new _Brand(ch, item.get("id").asInt(), i, item.get("name").asText()));
					}
				}
				log4j.info(_brands.size() + " brands");
				
				//id = 9
				_Brand b = _brands.get(0);
				eachBrand((ArrayNode)brandNode.get("A"), b);
				
				for (int i = 1; i < _brands.size(); i++) {
					json(_brands.get(i));
				}
			}else{
				eachBrand((ArrayNode)brandNode.get(_b.ch), _b);
			}
		}
	}
	
	public void eachBrand(ArrayNode an, _Brand b)throws IOException{
		log4j.info(b);
		ArrayNode children = (ArrayNode)an.get(b.index).get("child");
		for (JsonNode jn : children) {
			if(jn.get("type").asText().equals("cb")){
				ArrayNode children1 = (ArrayNode)jn.get("child");
				for (JsonNode jn1 : children1) {
					//"/serial/3395/
					eachCar(b.name, jn.get("name").asText(), jn1.get("name").asText(), jn1.get("url").asText().replace("/", "").replace("serial", ""));
				}
			}else{
				eachCar(b.name, null, jn.get("name").asText(), jn.get("url").asText().replace("/", "").replace("serial", ""));
			}
		}
	}
	
	public void eachCar(String brand, String brandType, String subBrand, String subBrandId){
		log4j.info(subBrand + " " + subBrandId);
		CarImage car = new CarImage();
		car.setBrand(brand);
		car.setBrandType(brandType);
		car.setSubBrand(subBrand);
		car.setSubBrandId(subBrandId);
		
		try {
			scrapeImageForEachCar(car);
		} catch (IOException e) {
			log4j.error(e.getMessage(), e);
			car.setStatus(5);
		}
		dao.save(car);
	}
	
	private void scrapeImageForEachCar(CarImage car) throws IOException{
		String subBrandId = car.getSubBrandId();
		String url = PREFIX + subBrandId + "/2014/11/1";
		Document doc = Jsoup.parse(new URL(url), TIMEOUT);
		Element thumbEle = doc.select(".carpic_list a").first();
		if(thumbEle == null){
			car.setStatus(3);
			url = PREFIX1 + subBrandId +"/";
			doc = Jsoup.parse(new URL(url), TIMEOUT);
			thumbEle = doc.select(".carpic_list a").first();
			if(thumbEle == null){
				car.setStatus(4);
				return;
			}
		}
		
		doc = Jsoup.parse(new URL(thumbEle.attr("abs:href")), TIMEOUT);
		Elements imgs = doc.select("#smallimgswrapper img");
		int i = 0;
		for (Element img : imgs) {
			String src = img.attr("src");
			log4j.info("img: " + src);
			String src1 = getBigImageSrc(src, 8);
			try {
				extractor.scrape(src1, car, i);
			} catch (Exception e) {
				src1 = getBigImageSrc(src, 16);
				extractor.scrape(src1, car, i);
				car.setStatus(2);;
			}
			String filename = subBrandId + "_" + (i++) + ".jpg";
			if(i == 1){
				car.setImage1(filename);
			}
			else if(i == 2){
				car.setImage2(filename);
			}
			else if(i == 3){
				car.setImage3(filename);
			}
			else if(i == 4){
				car.setImage4(filename);
				break;
			}
		}
	}
	
	//http://photo.bitauto.com/API/GetSourceImageListForSerialBrand.ashx?serialBrandID=3999&sourceID={0}&pageNum=1&pageSize=40
	public List<_Image> scrapeImageList(String subBrandId) throws IOException{
		//scrape official image first
		String url = MessageFormat.format(IMAGE_LIST, 11, subBrandId);
		String result = sendRequest(url, false);
		ArrayNode array = (ArrayNode)om.readTree(result);
		List<_Image> list = new ArrayList<>();
		for (int i = 0; i < array.size(); i++) {
			String pattern = array.get(i).get("Url").asText();
			list.add(new _Image(MessageFormat.format(pattern, 8), MessageFormat.format(pattern, 2)));
		}
		
		//scrape car show image
		url = MessageFormat.format(IMAGE_LIST, 17, subBrandId);
		result = sendRequest(url, false);
		array = (ArrayNode)om.readTree(result);
		for (int i = 0; i < array.size(); i++) {
			String pattern = array.get(i).get("Url").asText();
			list.add(new _Image(MessageFormat.format(pattern, 12), MessageFormat.format(pattern, 2)));
		}
		
		return list;
	}
	
	private String getBigImageSrc(String small, int size){
		int i = small.lastIndexOf("2.");
		return small.substring(0, i) + size + small.substring(i + 1);
	}
	
	@Deprecated
	public void cars(String brand, String brandType, Element parentEle)throws IOException{
		Elements cars = parentEle.select(".subBrand");
		for (Element e : cars) {
			String href = e.attr("href");
			String subBrandId = href.replace("/", "").replace("serial", "");
			String subBrand = e.child(0).text();
			
			CarImage car = new CarImage();
			car.setBrand(brand);
			car.setBrandType(brandType);
			car.setSubBrand(subBrand);
			car.setSubBrandId(subBrandId);
			
			String url = e.attr("abs:href");
			//http://photo.bitauto.com/serial/3999/
			//http://photo.bitauto.com/serialmore/3999/2014/11/1/#photoanchor 官方图
			url = url.replace(subBrandId, subBrandId + "/2014/11/1").replace("serial", "serialmore");
			Document doc = Jsoup.parse(new URL(url), TIMEOUT);
			Elements imgs = doc.select("#smallimgswrapper img");
			int i = 0;
			for (Element img : imgs) {
				String src = img.attr("src");
				log4j.info("img: " + img.attr("src"));
				String filename = subBrandId + "_" + (i++) + ".jpg";
				File f = new File(FileSystemUtil.getCarImage(), filename);
				FileUtils.copyURLToFile(new URL(src), f);
			}
		}
	}
	
	public String scrapeUrlBySubBrandId(CarImage car, String imageId, int i)throws IOException{
		//http://photo.bitauto.com/picture/2837/3760232/
		String subBrandId = car.getSubBrandId();
		String url = PREFIX2 + subBrandId + "/" + imageId + "/";
		Document doc = Jsoup.parse(new URL(url), TIMEOUT);
		Element img = doc.select("#smallimgswrapper .current img").first();
		String src = img.attr("src");
		log4j.info("img: " + src);
		String src1 = src.replace("2.jpg", "8.jpg").replace("2.JPG", "8.jpg");
		return src1;
	}
	
	class _Brand{
		String ch;
		int id;
		int index;
		String name;
		public _Brand(String ch, int id, int index, String name) {
			super();
			this.ch = ch;
			this.id = id;
			this.index = index;
			this.name = name;
		}
		
		@Override
		public String toString() {
			return "id=" + id + ", ch=" + ch + ", index=" + index + ", name=" + name;
		}
	}
	
	//车展（sourceId=17, big_image=12）， 官方图（sourceId=11,big_image=8）
	public class _Image{
		String url;
		String thumbUrl;
		public _Image(String url, String thumbUrl) {
			super();
			this.url = url;
			this.thumbUrl = thumbUrl;
		}
		
		public String getUrl() {
			return url;
		}
		
		public String getThumbUrl() {
			return thumbUrl;
		}
	}
	
	private String sendRequest(String s, boolean gzip){
		String result = null;
		InputStream in = null;
		try{
			URL url = new URL(s);
			HttpURLConnection conn = (HttpURLConnection)url.openConnection();
			HttpUtil.addHttpHeads(conn);
			if(gzip){
				in = new GZIPInputStream(conn.getInputStream());
			}else{
				in = conn.getInputStream();
			}
			result = IOUtils.toString(in);
		}catch(Exception e){
			log4j.warn(e.getMessage(), e);
		}finally {
			IOUtils.closeQuietly(in);
		}
		return result;
	}
	
	public static void main(String[] args) throws IOException {
		ImageService is = new ImageService();
		is.eachCar("", "", "", "3269");
//		is.start();
	}
}
